<script setup lang="ts">
  import { nextTick, ref, watch } from 'vue'
  import { Close } from '@element-plus/icons-vue'
  import useStyle from './styles/index'

  const {
    hDrawerWidthUnit,
    hDrawerMaskStyle,
    hDrawerBodyStyle,
    hDrawerLoadingStyle,
    hDrawerContainerStyle,
  } = useStyle()

  const props = defineProps<{
    modelValue: boolean
    width?: number
    unit?: '%' | 'px'
    title?: string
    loading?: boolean
    hDrawerPaddingTop?: number
    hDrawerPaddingLeft?: number
    hDrawerPaddingRight?: number
  }>()

  const emits = defineEmits<{
    (e: 'update:modelValue', value: boolean): void
    (e: 'close'): void
    (e: 'click'): void
  }>()

  const visible = ref(false)
  const hDrawerFooterRef = ref<HTMLElement | null>(null)
  const hDrawerHeaderRef = ref<HTMLElement | null>(null)

  const onClose = () => {
    visible.value = false
    emits('update:modelValue', visible.value)
    emits('close')
  }

  const setHDrawerBodyStyle = () => {
    let footerHeight = 0
    let headerHeight = 0
    if (hDrawerFooterRef.value) {
      footerHeight = hDrawerFooterRef.value.scrollHeight
    }

    if (hDrawerHeaderRef.value) {
      headerHeight = hDrawerHeaderRef.value.scrollHeight
    }

    hDrawerBodyStyle.value.height = `calc(100% - ${footerHeight + headerHeight}px)`
    hDrawerBodyStyle.value.paddingTop = `${props.hDrawerPaddingTop || 24}px`
    hDrawerBodyStyle.value.paddingLeft = `${props.hDrawerPaddingLeft || 30}px`
    hDrawerBodyStyle.value.paddingRight = `${props.hDrawerPaddingRight || 30}px`
  }

  watch(
    props,
    (value) => {
      if (props.width) {
        hDrawerContainerStyle.value.width = `${props.width}${hDrawerWidthUnit.value}`
      }
      if (props.unit) {
        hDrawerWidthUnit.value = props.unit
      }
      visible.value = value.modelValue

      if (visible.value) {
        nextTick(() => {
          setHDrawerBodyStyle()
        })
      }
    },
    { immediate: true, deep: true },
  )
</script>

<template>
  <teleport to="body">
    <transition name="h_drawer">
      <div v-if="visible" class="h_drawer_mask" :style="hDrawerMaskStyle">
        <div class="h_drawer_container" :style="hDrawerContainerStyle" @click="emits('click')">
          <div class="h_drawer">
            <header ref="hDrawerHeaderRef" class="h_drawer_header">
              <div class="title">
                <slot name="title">
                  <span>{{ props.title || '' }}</span>
                </slot>
              </div>
              <div class="close" @click="onClose">
                <el-icon :size="16">
                  <Close />
                </el-icon>
              </div>
            </header>
            <div class="d_drawer_body" :style="hDrawerBodyStyle">
              <slot></slot>
            </div>
            <footer v-if="$slots.footer" ref="hDrawerFooterRef" class="h_drawer_footer">
              <slot name="footer"></slot>
            </footer>

            <div v-if="props.loading" class="h_drawer_loading" :style="hDrawerLoadingStyle">
              <i class="iconfont icon-refresh_2"></i>
            </div>
          </div>
        </div>
      </div>
    </transition>
  </teleport>
</template>

<style scoped lang="scss">
  @import './styles/HDrawer.scss';
</style>
